const constants = require('../helpers/constants');
const utils = require('../helpers/utils');

/**
 * 从sql语句中匹配出创建表格语句
 * @example
 * ```
 * create table admin
(
    `id`       int primary key auto_increment comment '管理员ID',
    `username` varchar(32) unique not null comment '管理员名',
    `password` varchar(32)        not null comment '管理员密码',
    `nick`     varchar(32) comment '管理员昵称',
    `avatar`   varchar(256) comment '管理员头像',
    `gender`   tinyint   default 0 comment '管理员性别：0 保密，1 男，2 女',
    `phone`    char(11) unique comment '管理员手机号',
    `email`    varchar(64) unique comment '管理员邮箱',
    `salt`     char(6) comment '管理员密码盐值',
    `status`   tinyint   default 0 comment '账号状态（0 账号未激活，1 账号激活，2 账号禁用）',
    `createAt` timestamp default current_timestamp comment '创建日期',
    `updateAt` timestamp default current_timestamp on update current_timestamp comment '更新日期'
) comment '管理员表';
 * ```
 * @param {String} sql sql语句
 */
function getTableSQL(sql) {
    return sql.match(/create\s+table\s+(\S+)\s*.*?;/gi);
}

/**
 * 获取创建表格的sql语句中的columnSQL
 * @param {String} createTableSql 创建表格的sql语句
 */
function getTableColumnSQL(createTableSql) {
    const bracketBegin = createTableSql.indexOf('(');
    const bracketEnd = createTableSql.lastIndexOf(')');
    return createTableSql
        .substring(bracketBegin + 1, bracketEnd)
        .split(',')
        .map((item) => item.trim());
}

/**
 * 获取表名（驼峰命名）
 * @param {String} createTableSql 创建表格的sql语句
 */
function getTableName(createTableSql) {
    const name = createTableSql.match(/create\s+table\s+(\S+)\s*\(/i)[1];
    return utils.underline2camelCase(utils.trimQuote(name));
}

/**
 * 获取表注释
 * @param {String} createTableSql 创建表格SQL语句
 */
function getTableComment(createTableSql) {
    const index = createTableSql.lastIndexOf(')');
    const sql = createTableSql.substring(index + 1, createTableSql.length);
    let matches = sql.match(/.*comment(\s+|\s*=\s*)'(.*?)'.*;$/i);
    if (matches && matches.length > 2) {
        return matches[2];
    }
    return null;
}

/**
 * 获取列名
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 */
function getColumnName(createTableColumnSql) {
    const name = createTableColumnSql.match(/^\S+/)[0];
    return utils.underline2camelCase(utils.trimQuote(name));
}

/**
 * 获取列字段类型
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 */
function getColumnType(createTableColumnSql) {
    const sqlTypes = Reflect.ownKeys(constants.SQL_TYPES).map((key) => key);
    const sqlTypesRegex = new RegExp(
        `\\s+(${sqlTypes.join('|')})(\\s*\\(\\s*\\S*\\s*\\))?\\s+`,
        'i'
    );
    return createTableColumnSql.match(sqlTypesRegex)[1];
}

/**
 * 获取列字段值长度
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 * 返回空值则不限制长度
 */
function getColumnValueLength(createTableColumnSql, columnType) {
    const regex = new RegExp(`\\s+${columnType}\s*\((\d+)\)\\s+`, 'i');
    const matches = createTableColumnSql.match(regex);
    if (matches && matches.length > 1) {
        return matches[1];
    }
    return null;
}

/**
 * 获取列字段注释
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 */
function getColumnComment(createTableColumnSql) {
    let matches = createTableColumnSql.match(/comment(\s+|\s*=\s*)'(.*?)'/i);
    if (matches && matches.length > 2) {
        return matches[2];
    }
    return null;
}

/**
 * 获取列字段默认值
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 */
function getColumnDefault(createTableColumnSql) {
    let matches = createTableColumnSql.match(/default\s+((\S+(\s*\(.*?\))?)|'.*?')\s*,?/i);
    if (matches && matches.length > 1) {
        // 去除首尾单引号
        return utils.trimQuote(matches[1]);
    }
    return null;
}

/**
 * 判断列字段是否必须
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 */
function isColumnRequired(createTableColumnSql) {
    let matches = createTableColumnSql.match(/(not\s+null)|(primary\s+key)/i);
    return matches && matches.length > 0;
}

/**
 * 判断列字段是否为主键
 * @param {String} createTableColumnSql 创建表格SQL语句中的列语句
 */
function isColumnPrimaryKey(createTableColumnSql) {
    let matches = createTableColumnSql.match(/primary\s+key/i);
    return matches && matches.length > 0;
}

/**
 * 转化为一个tableList对象
 * @param {String} sql sql语句
 * @returns
 */
function parse(sql) {
    const tableMatches = getTableSQL(sql);
    if (!tableMatches) {
        console.error('create table sql does not exist');
        return [];
    }
    return tableMatches.map((tableSql) => {
        const tableName = getTableName(tableSql);
        const tableComment = getTableComment(tableSql);
        const columns = getTableColumnSQL(tableSql);
        const table = {
            name: tableName,
            description: tableComment
        };
        table.fields = columns.map((column) => {
            const columnName = getColumnName(column);
            const columnType = getColumnType(column);
            const columnComment = getColumnComment(column);
            const columnValueLength = getColumnValueLength(column);
            const columnDefault = getColumnDefault(column);
            const columnRequired = isColumnRequired(column);
            const columnPrimaryKey = isColumnPrimaryKey(column);
            return {
                name: columnName,
                type: columnType.toLowerCase(),
                description: columnComment,
                valueLength: columnValueLength,
                default: columnDefault,
                required: columnRequired,
                primaryKey: columnPrimaryKey
            };
        });
        return table;
    });
}

module.exports = {
    getTableSQL,
    getTableColumnSQL,
    getTableName,
    getTableComment,
    getColumnName,
    getColumnType,
    getColumnValueLength,
    getColumnComment,
    getColumnDefault,
    parse
};
